package com.cl.blog.config;

import org.springframework.amqp.core.*;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.HashMap;
import java.util.Map;

/**
 * @Author 付
 * @Date 2024-04-01 11:11
 * @Version 1.0
 * @description rabbitmq消息队列配置
 * @since 1.0
 */
//@Configuration
public class RabbitMqConfig {
	/**
	 * TTL （time to live）
	 * 最大生存时间
	 * <p>
	 * dead queue
	 * 死信队列
	 * <p>
	 * 两者的关系：当用户发起延时请求时，rabbitmq对其设置ttl，将其放到延时队列中，
	 * 如果该消息的延时时间到达，那么就将其放入死信队列等待处理，
	 * <p>
	 * TTL有两中设置方式，一种是队列延时，一种是消息延时
	 * <p>
	 * 队列延时：给整个队列设置延时
	 * Map<String, Object> args = new HashMap<String, Object>();
	 * args.put("x-message-ttl", 6000);
	 * channel.queueDeclare(queueName, durable, exclusive, autoDelete, args);
	 * <p>
	 * 消息延时：给单独的消息进行延时设置
	 * AMQP.BasicProperties.Builder builder = new AMQP.BasicProperties.Builder();
	 * builder.expiration("6000");
	 * AMQP.BasicProperties properties = builder.build();
	 * channel.basicPublish(exchangeName, routingKey, mandatory, properties, "msg body".getBytes());
	 * <p>
	 * 两者区别在于，如果设置了队列的TTL属性，那么一旦消息过期，就会被队列丢弃，而第二种方式，消息即使过期，也不一定会被马上丢弃，
	 * 因为消息是否过期是在即将投递到消费者之前判定的，如果当前队列有严重的消息积压情况，则已过期的消息也许还能存活较长时间。
	 * 另外，还需要注意的一点是，如果不设置TTL，表示消息永远不会过期，如果将TTL设置为0，则表示除非此时可以直接投递该消息到消费者，否则该消息将会被丢弃。
	 */


//	public static final String DELAY_EXCHANGE_NAME = "delay.queue.content.business.exchange";
//	public static final String DEAD_LETTER_EXCHANGE = "delay.queue.content.deadletter.exchange";
	public static final String JAVABOY_QUEUE_NAME = "javaboy_queue_name";
	public static final String JAVABOY_EXCHANGE_NAME = "javaboy_exchange_name";
	public static final String JAVABOY_ROUTING_KEY = "javaboy_routing_key";
	public static final String DLX_QUEUE_NAME = "dlx_queue_name";
	public static final String DLX_EXCHANGE_NAME = "dlx_exchange_name";
	public static final String DLX_ROUTING_KEY = "dlx_routing_key";


	public static final String DELAYED_QUEUE_NAME = "delay.queue.demo.delay.queue";
	public static final String DELAYED_EXCHANGE_NAME = "delay.queue.demo.delay.exchange";
	public static final String DELAYED_ROUTING_KEY = "delay.queue.demo.delay.routingkey";


//	// 声明延时Exchange
//	@Bean("delayExchange")
//	public DirectExchange delayExchange() {
//		return new DirectExchange(DELAY_EXCHANGE_NAME);
//	}
//
//	// 声明死信Exchange
//	@Bean("deadLetterExchange")
//	public DirectExchange deadLetterExchange() {
//		return new DirectExchange(DEAD_LETTER_EXCHANGE);
//	}


	/**
	 * 死信队列
	 *
	 * @return
	 */
	@Bean
	Queue dlxQueue() {
		return new Queue(DLX_QUEUE_NAME, true, false, false);
	}

	/**
	 * 死信交换机
	 *
	 * @return
	 */
	@Bean
	DirectExchange dlxExchange() {
		return new DirectExchange(DLX_EXCHANGE_NAME, true, false);
	}

	/**
	 * 绑定死信队列和死信交换机
	 *
	 * @return
	 */
	@Bean
	Binding dlxBinding() {
		return BindingBuilder.bind(dlxQueue()).to(dlxExchange())
				.with(DLX_ROUTING_KEY);
	}

	/**
	 * 普通消息队列
	 *
	 * @return
	 */
	@Bean
	Queue javaboyQueue() {
		Map<String, Object> args = new HashMap<>();
		//设置消息过期时间
		args.put("x-message-ttl", 1000 * 10);
		//设置死信交换机
		args.put("x-dead-letter-exchange", DLX_EXCHANGE_NAME);
		//设置死信 routing_key
		args.put("x-dead-letter-routing-key", DLX_ROUTING_KEY);
		return new Queue(JAVABOY_QUEUE_NAME, true, false, false, args);
	}

	/**
	 * 普通交换机
	 *
	 * @return
	 */
	@Bean
	DirectExchange javaboyExchange() {
		return new DirectExchange(JAVABOY_EXCHANGE_NAME, true, false);
	}

	/**
	 * 绑定普通队列和与之对应的交换机
	 *
	 * @return
	 */
	@Bean
	Binding javaboyBinding() {
		return BindingBuilder.bind(javaboyQueue())
				.to(javaboyExchange())
				.with(JAVABOY_ROUTING_KEY);
	}


	// 声明延时队列D
	@Bean
	public Queue immediateQueue() {
		return new Queue(DELAYED_QUEUE_NAME);
	}

	// 声明交换机
	@Bean
	public CustomExchange customExchange() {
		Map<String, Object> args = new HashMap<>();
		args.put("x-delayed-type", "direct");
		return new CustomExchange(DELAYED_EXCHANGE_NAME, "x-delayed-message", true, false, args);
	}


	// 交换机绑定路由D
	@Bean
	public Binding bindingNotify(@Qualifier("immediateQueue") Queue queue,
								 @Qualifier("customExchange") CustomExchange customExchange) {
		return BindingBuilder.bind(queue).to(customExchange).with(DELAYED_ROUTING_KEY).noargs();
	}
}
